#ifndef ELEMENTO_H_
#define ELEMENTO_H_

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include  "Redimensionable.h"
#include "../Fisica/EntidadFisica.h"
#include <string>
#include "../constantes.h"
#include "../sonido/Sonido.h"
#include <list>

using namespace std;

class Elemento: public Redimensionable {

private:
	int anguloRotacion;
	string tipo;
	EntidadFisica* entidadFisica;
	int idElementoUnion1;
	int idElementoUnion2;
	list<string>* idUnionesEngranajes;
	bool pelotaAdentro;
	bool esFijo;
	bool visitadoEliminar;
	bool yaVisiteParaCrear;

public:
	Elemento(double x, double y, double ancho, double alto, string pathImagen);

	virtual ~Elemento();
	static void reiniciarId();

	string getPathImagen();
	void setPathImagen(string path);

	void rotar(SDL_Renderer* renderer, double grados);
	SDL_Texture* getTextura() {
		return this->texturaElemento;
	}
	SDL_Surface* getSurface() {
		return this->surfaceElemento;
	}

	void setAnguloRotacion(double);
	double getAnguloRotacion() const;
	const string& getTipo() const;
	void setTipo(const string& tipo);

	virtual void dibujar(double x, double y, double ancho, double alto,
			SDL_Renderer* renderer);
	virtual void actualizarValoresFisicos();
	virtual bool aceptaEngranaje();
	virtual void agregarEngranaje(Elemento*);
	virtual Elemento* obtenerEngranaje();
	virtual void eliminarEngranaje();
	virtual void eliminarEngranajeDeLista(Elemento*);
	virtual bool engranajeEnLista(Elemento*);
	void setElementoFisico(EntidadFisica* elementofisico);
	virtual void mover(double centroX, double centroY);
	virtual void rotar(double angulo);
	virtual int seSuperpone(Elemento* elemento);
	virtual void superponer(Elemento* elemento);
	virtual bool aceptaSoga();
	virtual void agregarSogaInicial(Elemento*);
	virtual void agregarSogaFinal(Elemento*);
	virtual void eliminarSoga(Elemento* soga);
	virtual pair<Elemento*,Elemento*> obtenerExtremos();
//	virtual pair<Elemento*,Elemento*> obtenerExtremosSoga();
//	virtual pair<Elemento*,Elemento*> obtenerExtremosCorrea();
//	virtual pair<Elemento*,Elemento*> obtenerExtremosBalancin();

	virtual bool aceptaCorrea();
	virtual void eliminarCorrea();
	virtual void agregarCorreaInicial(Elemento* correa);
	virtual void agregarCorreaFinal(Elemento* correa);

	virtual void setPosicionInicial(double x, double y);
	virtual void setPosicionFinal(double x, double y);
	virtual pair<double,double> getPosicionInicial();
	virtual pair<double,double> getPosicionFinal();
	virtual bool agregaEnVacio();
	virtual bool dejarEnCanvas(double x, double y);
	virtual bool tieneVertices();
	virtual void eliminarReferencias(list<Elemento*>* elementosCanvas);
	virtual void actualizarReferencias();

	virtual bool esBasico();
	virtual bool esAnimable();
	virtual bool entraEnCinta(list<Elemento*>*);
	virtual bool chequearIngresoCinta(Elemento* );
	void animar();

	void setListaIdUnionesEngranajes(list<string>*);
	list<string>* getListaIdUnionesEngranajes();

	void setIdElementoUnion1(int);
	void setIdElementoUnion2(int);
	int getIdElementoUnion1();
	int getIdElementoUnion2();
	virtual bool sogaEnPosInicial();
	virtual bool sogaEnPosFinal();
	virtual void actualizarImagen();
	void eliminarImagenElemento();
	bool fueVisitadoEnEliminar();
	void setFueVisitado(bool);
	bool fueVisitadoEnCrear();
	void setFueVisitadoCrear(bool);
	virtual void actualizarSonido();


	double getAltoPixeles() {
		return altoPixeles;
	}

	void setAltoPixeles(double altoPixeles) {
		this->altoPixeles = altoPixeles;
	}

	double getAnchoPixeles() {
		return anchoPixeles;
	}

	void setAnchoPixeles(double anchoPixeles) {
		this->anchoPixeles = anchoPixeles;
	}

	EntidadFisica* getEntidadFisica() {
		return this->entidadFisica;
	}

	void setEntidadFisica(EntidadFisica* entidadFisica) {
		this->entidadFisica = entidadFisica;
	}

	bool isRotaADerecha() {
		return rotaADerecha;
	}

	virtual void setRotaADerecha(bool rotaADerecha) {
		this->rotaADerecha = rotaADerecha;
	}

	unsigned int getTiempoSentidoRotacion() {
		return tiempoSentidoRotacion;
	}

	void setTiempoSentidoRotacion(unsigned int tiempoSentidoRotacion) {
		this->tiempoSentidoRotacion = tiempoSentidoRotacion;
	}

	virtual void jointearElemento(b2World* world);
	int getIdElemento();
	void setIdElemento(int id);

	bool isPelotaAdentro() {
		return pelotaAdentro;
	}

	void setPelotaAdentro(bool pelotaAdentro) {
		this->pelotaAdentro = pelotaAdentro;
	}

	bool isEsFijo() {
		return esFijo;
	}

	void setEsFijo(bool esFijo) {
		this->esFijo = esFijo;
	}

	bool rotaADerecha;

protected:
	string pathImagen;
	SDL_Texture* texturaElemento;
	SDL_Surface* surfaceElemento;
	double anchoPixeles, altoPixeles;
	unsigned int tiempoSentidoRotacion;
	int idElemento;
	int frameActual;
	int cantFrames;

};

#endif /* ELEMENTO_H_ */
